import os
import yaml

class Struct(dict):
    """
    - 功能：为字典加上点语法，实现 对象.属性 调用。
    - 例如:
    >>> d = Struct({'age':18})
    >>> d.age
    >>> 18
    >>> d.gender
    >>> None
    """
    def __init__(self, dictObj={}):
        self.update(dictObj)

    def __getattr__(self, name):
        # Pickle is trying to get state from your object, and dict doesn't implement it.
        # Your __getattr__ is being called with "__getstate__" to find that magic method,
        # and returning None instead of raising AttributeError as it should.
        if name.startswith('__'):
            raise AttributeError
        return self.get(name)

    def __setattr__(self, name, val):
        self[name] = val

    def __hash__(self):
        return id(self)

class Config(Struct):
    def __init__(self, args):
        self.config = self.load_yaml_config(args.cfg)
        self.config['train_flag'] = args.train_flag
        self.config = Struct(self.config)
        self.config = self.creat_config(self.config)
        self.config = self.conver_dict(self.config)

    def load_yaml_config(self, configfile):
        with open(configfile, 'r', encoding="utf-8") as f:
            cont = f.read()
            y = yaml.load(cont, Loader=yaml.FullLoader)
        return y

    def creat_config(self, config):
        if not os.path.exists(config.outputPath):
            print("[creat_config]: outputPath: {0} is not exit.".format(config.outputPath))
            exit(-2)

        if config.train_flag == 'train':
            verSionPath = os.path.join(config.outputPath, config.version)
            checkPointOutPath = os.path.join(verSionPath, 'checkpoint')
            config['train']['checkPoin'] = checkPointOutPath
            if not os.path.exists(checkPointOutPath):
                os.makedirs(checkPointOutPath)
            logOutPath = os.path.join(verSionPath, 'logs')
            config['train']['log'] = logOutPath
            if not os.path.exists(logOutPath):
                os.makedirs(logOutPath)

        config['model']['model_def'] = os.path.join('./config', config['model']['model_def']) + '.cfg'
        return config

    def conver_dict(self, config):
        if config['train_flag'] == 'train':
            train = Struct(config['train'])
        else:
            train = None
        test = Struct(config['test'])
        model = Struct(config['model'])
        config = Struct(dict(train=train, test=test, model=model,
                              train_flag=config['train_flag']))
        return config

    def get_config(self):
        return self.config


